<!--
 * Copyright © 2022
 * @Author: zhangxiang
 * @Date: 2022-11-21 17:13:52
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-08-16 09:53:19
 * @Description:
 *
-->

<template>
  <div class="permission-authority-container">
    <el-row type="flex" align="middle">
      <div style="font-size: 16px; font-weight: 500; margin-right: 20px">
        角色选择
      </div>
      <el-select
        v-model="roleSelect"
        size="small"
        style="width: 200px"
        placeholder="选择角色"
        @change="roleChange"
      >
        <el-option
          v-for="item in roleOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </el-row>
    <el-divider />
    <el-row type="flex" align="middle" style="margin-bottom: 15px">
      <div style="font-size: 20px; font-weight: bold">页面权限</div>
      <i class="el-icon-question" style="margin: 0 15px"></i>
      <div class="hint-block"></div>
      <div style="margin: 0 10px 0 5px">
        表示该权限受限，不能创建、删除，只能使用和浏览
      </div>
      <div class="hint-block block2"></div>
      <div style="margin: 0 10px 0 5px">
        表示该权限受限，不能创建、删除和编辑，只能浏览
      </div>
    </el-row>
    <el-card class="category" shadow="hover">
      <div slot="header">用户权限</div>
      <div class="check-wrapper">
        <div
          v-for="(authority, aindex) in userAuthority"
          :key="aindex"
          class="check-item"
          @click.prevent="authorityClick(authority)"
        >
          <el-checkbox
            v-model="authority.checked"
            :class="[getCheckboxClass(authority.permissions)]"
            :disabled="authority.disabled || roleSelectDefault"
          >{{ authority.label }}</el-checkbox>
        </div>
      </div>
    </el-card>
    <el-card class="category" shadow="hover">
      <div slot="header">系统权限</div>
      <div
        v-for="(item, index) in Object.keys(systemAuthority)"
        :key="index"
        :class="['sys', index === 0 ? 'first' : '']"
      >
        <div v-if="systemAuthority[item].length > 1" class="title">
          {{ item }}
        </div>
        <div class="check-wrapper">
          <div
            v-for="(authority, aindex) in systemAuthority[item]"
            :key="aindex"
            class="check-item"
            @click.prevent="authorityClick(authority)"
          >
            <el-checkbox
              v-model="authority.checked"
              :class="[getCheckboxClass(authority.permissions)]"
              :disabled="authority.disabled || roleSelectDefault"
            >{{ authority.label }}</el-checkbox>
          </div>
        </div>
      </div>
    </el-card>
    <el-row type="flex" justify="end">
      <el-button
        size="medium"
        type="primary"
        :disabled="!submitEnable"
        :loading="submitLoading"
        @click="submitClick"
      >提 交</el-button>
    </el-row>

    <el-dialog
      :visible.sync="showDetailDialog"
      title="资源权限"
      width="350px"
      top="15vh"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      @close="showDetailDialog = false"
    >
      <el-checkbox-group
        v-model="detailPermissions"
        style="margin: 20px 0 0 30px"
      >
        <el-checkbox
          v-for="item in permissionOption"
          :key="item.key"
          style="width: 100px; margin-bottom: 20px"
          :label="item.key"
          :value="item.key"
        ><span>{{ item.label }}</span></el-checkbox>
      </el-checkbox-group>
      <div slot="footer" class="dialog-footer">
        <el-button
          size="small"
          @click="showDetailDialog = false"
        >取 消</el-button>
        <el-button
          type="primary"
          size="small"
          @click="detailConfirmClick"
        >确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getAllRole, updateRoleAuth, roleDetail } from '@/api/user'

const DEFAULT_ROLES = ['1', '2', '3']
const USER_AUTHORITY_NAMES = ['用户审核', '角色管理', '权限管理', '用户管理']

// 新增的角色默认不支持的权限KEY，用于新增的角色修改权限时过滤
const NORMAL_ROLE_UNABLE_AUTHORITY = [
  'SystemMgmtVerify',
  'SystemMgmtRoles',
  'SystemMgmtAuthority',
  'SystemMgmtUsers',
  'SystemMgmtMenu',
  'SystemMonitorCNRes'
]
// 不支持修改的权限KEY
const ROLE_UNSETTING_AUTHORITY = ['CNList']

export default {
  components: {},
  data() {
    return {
      onlyOneChild: null,
      roleOptions: [],
      roleSelect: '',
      allAuthority: [],
      submitLoading: false,
      showDetailDialog: false,
      detailKey: '',
      detailPermissions: [],
      permissionOption: [
        {
          key: 'create',
          label: '创建资源'
        },
        {
          key: 'delete',
          label: '删除资源'
        },
        {
          key: 'use',
          label: '使用资源'
        },
        {
          key: 'browse',
          label: '浏览资源'
        }
      ],
      clickCount: 0,
      clickTimer: null
    }
  },
  computed: {
    ...mapGetters(['permission_routers']),
    /**
     * @description: 提交按钮可用
     * @return {*}
     */
    submitEnable() {
      return this.roleSelect && !this.roleSelectDefault
    },
    /**
     * @description: 当前角色是否为默认角色
     * @return {*}
     */
    roleSelectDefault() {
      return DEFAULT_ROLES.includes(this.roleSelect)
    },
    /**
     * @description: 用户权限
     * @return {*}
     */
    userAuthority() {
      return this.allAuthority.filter((item) => {
        return item.type === '用户权限'
      })
    },
    /**
     * @description: 系统权限
     * @return {*}
     */
    systemAuthority() {
      const obj = {}
      for (const item of this.allAuthority) {
        if (item.type !== '用户权限') {
          if (Object.prototype.hasOwnProperty.call(obj, item.type)) {
            obj[item.type].push(item)
          } else {
            obj[item.type] = [item]
          }
        }
      }
      return obj
    }
  },
  created() {
    this.initData()
  },
  methods: {
    /**
     * @description: 资源权限-确定
     * @return {*}
     */
    detailConfirmClick() {
      const index = this.allAuthority.findIndex((item) => {
        return item.key === this.detailKey
      })
      if (index > -1) {
        this.allAuthority[index].permissions = this.detailPermissions
        this.allAuthority[index].checked = this.detailPermissions.length > 0
      }
      this.showDetailDialog = false
    },
    /**
     * @description: 点击
     * @param {*} authority
     * @return {*}
     */
    authorityClick(authority) {
      if (authority.disabled) {
        return
      }
      this.clickCount++
      if (this.clickCount === 1) {
        this.clickTimer = setTimeout(() => {
          this.clickCount = 0
          // 单击
          this.authoritySingleClick(authority)
        }, 250)
      } else {
        this.clickTimer && clearTimeout(this.clickTimer)
        this.clickCount = 0
        // 双击
        this.authorityDbClick(authority)
      }
    },
    /**
     * @description: 单击
     * @param {*} authority
     * @return {*}
     */
    authoritySingleClick(authority) {
      authority.checked = !authority.checked
      const index = this.allAuthority.findIndex((item) => {
        return item.key === authority.key
      })
      if (index > -1) {
        this.allAuthority[index].permissions = authority.checked
          ? ['create', 'delete', 'browse', 'use']
          : []
      }
    },
    /**
     * @description: 双击
     * @param {*} authority
     * @return {*}
     */
    authorityDbClick(authority) {
      this.detailKey = authority.key
      this.detailPermissions = authority.permissions
      this.showDetailDialog = true
    },
    /**
     * @description: 提交
     * @return {*}
     */
    submitClick() {
      this.submitLoading = true
      const pagePermissions = {}
      for (const item of this.allAuthority) {
        if (
          (item.disabled && ROLE_UNSETTING_AUTHORITY.includes(item.key)) ||
          (!item.disabled && item.checked && item.permissions.length > 0)
        ) {
          pagePermissions[item.key] = item.permissions
        }
      }
      updateRoleAuth({
        roleIndex: this.roleSelect,
        pagePermissions: JSON.stringify(pagePermissions)
      })
        .then((res) => {
          this.$message.success('权限设置成功')
          setTimeout(() => {
            window.location.reload()
          }, 1500)
        })
        .finally(() => {
          this.submitLoading = false
        })
    },
    /**
     * @description: 复选框样式
     * @param {*} permissions
     * @return {*}
     */
    getCheckboxClass(permissions) {
      let checkboxClass = 'common'
      if (permissions.length === 1 && permissions.includes('browse')) {
        // 只能浏览 严重受限
        checkboxClass = 'severelylimited'
      }
      if (
        permissions.length === 2 &&
        permissions.includes('browse') &&
        permissions.includes('use')
      ) {
        // 只能使用和浏览 普通受限
        checkboxClass = 'normallimited'
      }
      return checkboxClass
    },
    /**
     * @description: 处理角色权限
     * @param {*} rolePermissions
     * @return {*}
     */
    handleRoleAuthority(rolePermissions) {
      for (const item of this.allAuthority) {
        if (Object.prototype.hasOwnProperty.call(rolePermissions, item.key)) {
          item.permissions = rolePermissions[item.key]
          item.checked =
            Array.isArray(item.permissions) && item.permissions.length > 0
        } else {
          item.permissions = []
          item.checked = false
        }
        if (
          this.roleSelectDefault ||
          (!this.roleSelectDefault &&
            NORMAL_ROLE_UNABLE_AUTHORITY.includes(item.key)) ||
          ROLE_UNSETTING_AUTHORITY.includes(item.key)
        ) {
          // 默认角色 不支持修改权限
          // 非默认角色且相应权限属于不支持的权限 不支持修改权限
          // 不支持修改的权限KEY 不支持修改权限
          item.disabled = true
        } else {
          item.disabled = false
        }
      }
    },
    /**
     * @description: 改变角色-获取角色详情
     * @param {*} val
     * @return {*}
     */
    roleChange(val) {
      roleDetail({
        roleIndex: val
      }).then((res) => {
        const rolePermissions = res.data || {}
        this.handleRoleAuthority(rolePermissions)
      })
    },
    /**
     * @description: 获取角色列表
     * @return {*}
     */
    getRoleList() {
      getAllRole().then((res) => {
        this.roleOptions = Array.isArray(res.data) ? res.data : []
      })
    },
    /**
     * @description: 是否只有一个菜单
     * @param {*} children
     * @param {*} parent
     * @return {*}
     */
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter((item) => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          this.onlyOneChild = item
          return true
        }
      })

      // When there is only one child router, the child router is displayed by default
      if (showingChildren.length === 1) {
        return true
      }

      // Show parent if there are no child router to display
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ...parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    /**
     * @description: 遍历过滤路由
     * @return {*}
     */
    filterMenuRoutes() {
      for (const item of this.permission_routers) {
        if (!item.hidden) {
          if (
            this.hasOneShowingChild(item.children, item) &&
            (!this.onlyOneChild.children ||
              this.onlyOneChild.noShowingChildren) &&
            !item.alwaysShow
          ) {
            if (this.onlyOneChild.meta) {
              this.allAuthority.push({
                type: this.onlyOneChild.meta.title,
                key: this.onlyOneChild.meta.menuKey,
                label: this.onlyOneChild.meta.title,
                permissions: [],
                checked: false,
                disabled: true
              })
            }
          } else {
            if (item.meta) {
              for (const child of item.children) {
                if (!child.hidden && child.meta) {
                  this.allAuthority.push({
                    type: USER_AUTHORITY_NAMES.includes(child.meta.title)
                      ? '用户权限'
                      : item.meta.title,
                    key: child.meta.menuKey,
                    label: child.meta.title,
                    permissions: [],
                    checked: false,
                    disabled: true
                  })
                }
              }
            }
          }
        }
      }
    },
    initData() {
      this.filterMenuRoutes()
      this.getRoleList()
    }
  }
}
</script>
<style lang="less" scoped>
@import "@/assets/css/common.less";

.permission-authority-container {
  box-sizing: border-box;
  background: #ffffff;
  box-shadow: 0px 0px 5px 0px rgba(217, 213, 234, 0.5);
  border-radius: 8px;
  margin: 20px;
  min-height: calc(100vh - 90px);
  padding: 20px 30px;

  .hint-block {
    width: 13px;
    height: 13px;
    background: rgba(38, 175, 210, 1);
    display: inline-block;
    border-radius: 3px;
    &.block2 {
      background: rgba(247, 181, 0, 1);
    }
  }

  .category {
    margin-bottom: 20px;
    /deep/ .el-card__header {
      padding: 7px 20px;
      background: #fafafa;
      .textStyle(16px, 500, #262626);
    }
    /deep/ .el-card__body {
      padding: 15px 20px;
    }

    .sys {
      margin-top: 20px;
      &.first {
        margin-top: 0;
      }
      .title {
        .textStyle(14px, 500, #696969);
        line-height: 20px;
        margin-bottom: 10px;
      }
    }
    .check-wrapper {
      .check-item {
        display: inline-block;
        margin-right: 20px;
      }
      /deep/ .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
        background-color: #66bdff;
        border-color: #66bdff;
        &::after {
          border-color: #ffffff;
        }
      }
      .severelylimited {
        /deep/ .el-checkbox__input.is-checked + .el-checkbox__label {
          color: #f7b500;
        }
      }
      .normallimited {
        /deep/ .el-checkbox__input.is-checked + .el-checkbox__label {
          color: #26afd2;
        }
      }
    }
  }
}
</style>
<style lang="less">
.permission-authority-container {
  height: auto;
  background: #ffffff;
  padding: 40px;
  .result {
    color: rgba(105, 105, 105, 1) !important;
    &.common {
      color: rgba(105, 105, 105, 1) !important;
    }

    &.severelylimited {
      color: rgba(247, 181, 0, 1) !important;
    }

    &.normallimited {
      color: rgba(38, 175, 210, 1) !important;
    }
  }
}
</style>
